﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Xml.Serialization;
using Point = System.Windows.Point;

namespace OneOfAll.Common.Models
{
    public class ConstructionModel : BaseObjectModel
    {
        private bool isInit = false;
        public bool IsInit
        {
            get { return isInit; }
            set { isInit = value; RaisePropertyChanged(); }
        }

        private int maxCount = 0;
        public int MaxCount
        {
            get { return maxCount; }
            set { maxCount = value; RaisePropertyChanged(); }
        }

        private int quality = 1;
        public int Quality
        {
            get { return quality; }
            set { quality = value; RaisePropertyChanged(); }
        }

        private int durability = 100;
        public int Durability
        {
            get { return durability; }
            set { durability = value; RaisePropertyChanged(); }
        }

        private int exp_Work = 10;
        public int Exp_Work
        {
            get { return exp_Work; }
            set { exp_Work = value; RaisePropertyChanged(); }
        }

        public double DurablityEffect
        {
            get
            {
                if (Durability >= 80)
                    return 1.0;
                else if (Durability >= 50)
                    return 0.8;
                else if (Durability >= 30)
                    return 0.5;
                else
                    return 0.2;
            }
        }

        private bool isMaintain = true;
        public bool IsMaintain
        {
            get { return isMaintain; }
            set { isMaintain = value; RaisePropertyChanged(); }
        }

        private int angle = 0;
        public int Angle
        {
            get { return angle; }
            set { angle = value; RaisePropertyChanged(); }
        }

        private bool enabled = true;
        public bool Enabled
        {
            get { return enabled; }
            set { enabled = value; RaisePropertyChanged(); }
        }

        private bool limit = false;
        public bool Limit
        {
            get { return limit; }
            set { limit = value; RaisePropertyChanged(); }
        }

        private ConstructionTypeEnum constructionType = ConstructionTypeEnum.居住;
        public ConstructionTypeEnum ConstructionType
        {
            get { return constructionType; }
            set
            {
                constructionType = value;
                RaisePropertyChanged();
            }
        }

        public Brush Color
        {
            get
            {
                switch (constructionType)
                {
                    case ConstructionTypeEnum.居住:
                        return Brushes.Yellow;
                    case ConstructionTypeEnum.生产:
                        return Brushes.LightSeaGreen;
                    case ConstructionTypeEnum.培养:
                        return Brushes.LightGreen;
                    default:
                        return Brushes.LightGreen;
                }
            }
        }

        private int entranceX = 0;
        public int EntranceX
        {
            get { return entranceX; }
            set { entranceX = value; RaisePropertyChanged(); }
        }

        private int entranceY = 0;
        public int EntranceY
        {
            get { return entranceY; }
            set { entranceY = value; RaisePropertyChanged(); }
        }

        private int maxPeopleCount = 1;
        public int MaxPeopleCount
        {
            get { return maxPeopleCount; }
            set { maxPeopleCount = value; RaisePropertyChanged(); }
        }

        private int health = 0;
        public int Health
        {
            get { return health; }
            set { health = value; RaisePropertyChanged(); }
        }

        private int beauty = 0;
        public int Beauty
        {
            get { return beauty; }
            set { beauty = value; RaisePropertyChanged(); }
        }

        private int comfort = 0;
        public int Comfort
        {
            get { return comfort; }
            set { comfort = value; RaisePropertyChanged(); }
        }

        private int influence_Range = 20;
        public int Influence_Range
        {
            get { return influence_Range; }
            set {  influence_Range = value; RaisePropertyChanged(); }
        }

        private int influence_Health = 0;
        public int Influence_Health
        {
            get { return influence_Health; }
            set { influence_Health = value; RaisePropertyChanged(); }
        }

        private int influence_Beauty = 0;
        public int Influence_Beauty
        {
            get { return influence_Beauty; }
            set { influence_Beauty = value; RaisePropertyChanged(); }
        }

        private int influence_Comfort = 0;
        public int Influence_Comfort
        {
            get { return influence_Comfort; }
            set { influence_Comfort = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<Point> pointList = new ObservableCollection<Point>();
        public ObservableCollection<Point> PointList
        {
            get { return pointList; }
            set { pointList = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<PeopleWorkInfoModel> peopleList = new ObservableCollection<PeopleWorkInfoModel>();
        public ObservableCollection<PeopleWorkInfoModel> PeopleList
        {
            get { return peopleList; }
            set { peopleList = value; RaisePropertyChanged(); }
        }


        private ObservableCollection<int> plan_PeopleList = new ObservableCollection<int>();
        public ObservableCollection<int> Plan_PeopleList
        {
            get { return plan_PeopleList; }
            set { plan_PeopleList = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<ConstructionInfuenceModel> influenceList = new ObservableCollection<ConstructionInfuenceModel>();
        public ObservableCollection<ConstructionInfuenceModel> InfluenceList
        {
            get { return influenceList; }
            set { influenceList = value; RaisePropertyChanged(); }
        }

        private MaterialsResourceModel materialsResource = new MaterialsResourceModel();
        public MaterialsResourceModel MaterialsResource
        {
            get { return materialsResource; }
            set {  materialsResource = value; RaisePropertyChanged();}
        }

        private LiveInfoModel liveInfo = new LiveInfoModel();
        public LiveInfoModel LiveInfo
        {
            get { return liveInfo; }
            set { liveInfo = value; RaisePropertyChanged(); }
        }

        private ProductionInfoModel productionInfo = new ProductionInfoModel();
        public ProductionInfoModel ProductionInfo
        {
            get { return productionInfo; }
            set { productionInfo = value; RaisePropertyChanged(); }
        }

        private ResourceInfoModel resourceInfo = new ResourceInfoModel();
        public ResourceInfoModel ResourceInfo
        {
            get { return resourceInfo; }
            set { resourceInfo = value; RaisePropertyChanged(); }
        }

        private TrainInfoModel trainInfo = new TrainInfoModel();
        public TrainInfoModel TrainInfo
        {
            get { return trainInfo; }
            set { trainInfo = value; RaisePropertyChanged(); }
        }

        private MakeInfoModel makeInfo = new MakeInfoModel();
        public MakeInfoModel MakeInfo
        {
            get { return makeInfo; }
            set { makeInfo = value; RaisePropertyChanged(); }
        }

        public void RefushPoints()
        {
            int startX = 0;
            int startY = 0;
            int _width = 0;
            int _height = 0;
            PointList.Clear();
            switch (Angle)
            {
                case 0:
                    EntranceX = (int)X + (Width / Global.GlobalResource.GridSize / 2);
                    EntranceY = (int)Y + (Height / Global.GlobalResource.GridSize - 1);
                    _width = Width / Global.GlobalResource.GridSize;
                    _height = Height / Global.GlobalResource.GridSize;
                    break;
                case 90:
                    EntranceX = (int)X - (Height / Global.GlobalResource.GridSize - 1) - 1;
                    EntranceY = (int)Y + (Width / Global.GlobalResource.GridSize / 2);
                    startX = -Height / Global.GlobalResource.GridSize;
                    _height = Width / Global.GlobalResource.GridSize;
                    break;
                case 180:
                    EntranceX = (int)X - (Width / Global.GlobalResource.GridSize / 2) - 1;
                    EntranceY = (int)Y - (Height / Global.GlobalResource.GridSize) - 1;
                    startX = -Width / Global.GlobalResource.GridSize;
                    startY = -Height / Global.GlobalResource.GridSize;
                    break;
                case 270:
                    EntranceX = (int)X + (Height / Global.GlobalResource.GridSize - 1);
                    EntranceY = (int)Y - (Width / Global.GlobalResource.GridSize / 2) - 1;
                    _width = Height / Global.GlobalResource.GridSize;
                    startY = -Width / Global.GlobalResource.GridSize;
                    break;
            }
            for (int x = startX; x < _width; x++)
            {
                for (int y = startY; y < _height; y++)
                {
                    PointList.Add(new Point((int)X + x, (int)Y + y));
                }
            }
        }

        public ConstructionInfuenceModel GetConstructionInfluence()
        {
            return new ConstructionInfuenceModel() { Key = Key, Name = Name, Beauty = Beauty, Comfort = Comfort, Health = Health };
        }

        public ConstructionModel()
        {
            PropertyChangedHand();
            CollectionChangedHand();
        }

        private void CollectionChangedHand()
        {
            ProductionInfo.ResourceKeyList.CollectionChanged += ResourceKeyList_CollectionChanged;
            InfluenceList.CollectionChanged += InfluenceList_CollectionChanged;
        }

        private void InfluenceList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            Influence_Health = InfluenceList.Sum(t => t.Health);
            Influence_Beauty = InfluenceList.Sum(t => t.Beauty);
            Influence_Comfort = InfluenceList.Sum(t => t.Comfort);
        }

        private void ResourceKeyList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            RefushForecastYield();
        }

        private void PropertyChangedHand()
        {
            PropertyChanged += ConstructionModel_PropertyChanged;
            ProductionInfo.PropertyChanged += ProductionInfo_PropertyChanged;
        }

        private void ConstructionModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "Influence_Health":
                case "Influence_Beauty":
                case "Influence_Comfort":
                    RefushForecastYield();
                    break;
            }
        }



        private void ProductionInfo_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "ResourceDemandCount":
                case "CurrentEffect":
                    RefushForecastYield();
                    break;
            }
        }

        private void RefushForecastYield()
        {

            ProductionInfo.ForecastYield = (int)(ProductionInfo.BaseYield * (100 + Influence_Beauty) / 100.0 * (100 + Influence_Comfort) / 100.0 * (100 + Influence_Health) / 100.0 *
                (ProductionInfo.ResourceDemandCount > 0 ? ((double)ProductionInfo.ResourceKeyList.Count / (double)ProductionInfo.ResourceDemandCount) : 1) *
                ((double)ProductionInfo.CurrentEffect / 100.0) * DurablityEffect);
        }
    }

    public class LiveInfoModel : BaseModel
    {
        private int restRatio = 10;
        public int RestRatio
        {
            get { return restRatio; }
            set { restRatio = value; RaisePropertyChanged(); }
        }

        private int taxes = 100;
        public int Taxes
        {
            get { return taxes; }
            set { taxes = value; RaisePropertyChanged(); }
        }

        private ConsumablesInfoModel consumablesInfo = new ConsumablesInfoModel();
        public ConsumablesInfoModel ConsumablesInfo
        {
            get { return consumablesInfo; }
            set { consumablesInfo = value; RaisePropertyChanged(); }
        }
    }

    public class ConsumablesInfoModel : BaseModel
    {
        private ObservableCollection<ConsumablesModel> consumableList = new ObservableCollection<ConsumablesModel>();
        public ObservableCollection<ConsumablesModel> ConsumableList
        {
            get { return consumableList; }
            set { consumableList = value; RaisePropertyChanged(); }
        }
    }

    public class ResourceInfoModel : BaseModel
    {
        private ResourceTypeEnum resourceType = ResourceTypeEnum.无;
        public ResourceTypeEnum ResourceType
        {
            get { return resourceType; }
            set { resourceType = value; RaisePropertyChanged(); }
        }

        private int onwer = -1;
        public int Onwer
        {
            get { return onwer; }
            set { onwer = value; RaisePropertyChanged(); }
        }
    }


    public class ProductionInfoModel : BaseModel
    {
        private MaterialsTypeEnum productionType = MaterialsTypeEnum.金钱;
        public MaterialsTypeEnum ProductionType
        {
            get { return productionType; }
            set { productionType = value; RaisePropertyChanged(); }
        }

        private ResourceTypeEnum resourceDemand = ResourceTypeEnum.无;
        public ResourceTypeEnum ResourceDemand
        {
            get { return resourceDemand; }
            set { resourceDemand = value; RaisePropertyChanged(); }
        }

        private double workload = 100;
        public double Workload
        {
            get { return workload; }
            set { workload = value; RaisePropertyChanged(); }
        }

        private int baseYield = 0;
        public int BaseYield
        {
            get { return baseYield; }
            set { baseYield = value; RaisePropertyChanged(); }
        }

        private int forecastYield = 0;
        public int ForecastYield
        {
            get { return forecastYield; }
            set { forecastYield = value; RaisePropertyChanged(); }
        }

        private double currentEffect = 0.0;
        public double CurrentEffect
        {
            get { return currentEffect; }
            set { currentEffect = value; RaisePropertyChanged(); }
        }

        private int resourceDemandCount = 1;
        public int ResourceDemandCount
        {
            get { return resourceDemandCount; }
            set { resourceDemandCount = value; RaisePropertyChanged(); }
        }

        private ObservableCollection<int> resourceKeyList = new ObservableCollection<int>();
        public ObservableCollection<int> ResourceKeyList
        {
            get { return resourceKeyList; }
            set { resourceKeyList = value; RaisePropertyChanged(); }
        }

        private int resourceRange = 30;
        public int ResourceRange
        {
            get { return resourceRange; }
            set { resourceRange = value; RaisePropertyChanged(); }
        }


    }

    public class TrainInfoModel : BaseModel
    {
        private int train_Power = 0;
        public int Train_Power
        {
            get { return train_Power; }
            set { train_Power = value; RaisePropertyChanged(); }
        }

        private int train_trick = 0;
        public int Train_Trick
        {
            get { return train_trick; }
            set { train_trick = value; RaisePropertyChanged(); }
        }

        private int train_Strong = 0;
        public int Train_Strong
        {
            get { return train_Strong; }
            set { train_Strong = value; RaisePropertyChanged(); }
        }

        private int train_Wit = 0;
        public int Train_Wit
        {
            get { return train_Wit; }
            set { train_Wit = value; RaisePropertyChanged(); }
        }

        private int workLoad = 100;
        public int WorkLoad
        {
            get { return workLoad; }
            set { workLoad = value; RaisePropertyChanged(); }
        }

        private MaterialsResourceModel cost = new MaterialsResourceModel();
        public MaterialsResourceModel Cost
        {
            get { return cost; }
            set { cost = value; RaisePropertyChanged(); }
        }
    }

    public class MakeInfoModel : BaseModel
    {
        private int workLoad = 100;
        public int WorkLoad
        {
            get { return workLoad; }
            set { workLoad = value; RaisePropertyChanged(); }
        }

        private ProductTypeEnum productType = ProductTypeEnum.普通食物;
        public ProductTypeEnum ProductType
        {
            get { return productType; }
            set { productType = value; RaisePropertyChanged(); }
        }

        private MaterialsResourceModel cost = new MaterialsResourceModel();
        public MaterialsResourceModel Cost
        {
            get { return cost; }
            set { cost = value; RaisePropertyChanged(); }
        }

    }

    public class ConstructionPathModel : BaseModel
    {
        private string name = string.Empty;
        public string Name
        {
            get { return name; }
            set { name = value; RaisePropertyChanged(); }
        }

        public List<Point> Path { get; set; }
    }

    public class ConstructionInfuenceModel : BaseModel
    {
        private string name = string.Empty;
        public string Name
        {
            get { return name; }
            set { name = value; RaisePropertyChanged(); }
        }

        private int health = 0;
        public int Health
        {
            get { return health; }
            set { health = value; RaisePropertyChanged(); }
        }

        private int beauty = 0;
        public int Beauty
        {
            get { return beauty; }
            set { beauty = value; RaisePropertyChanged(); }
        }

        private int comfort = 0;
        public int Comfort
        {
            get { return comfort; }
            set { comfort = value; RaisePropertyChanged(); }
        }
    }

    public class ConsumablesModel : BaseModel
    {
        private ProductTypeEnum type = ProductTypeEnum.普通食物;
        public ProductTypeEnum Type
        {
            get { return type; }
            set { type = value; RaisePropertyChanged();}
        }

        private int num = 1;
        public int Num
        {
            get { return num; }
            set { num = value; RaisePropertyChanged(); }
        }

        private ConsumablesStatusEnum status = ConsumablesStatusEnum.满足;
        public ConsumablesStatusEnum Status
        {
            get { return status; }
            set { status = value; RaisePropertyChanged(); }
        }
    }
}